#include "manano_common.h"

#include "mdtx-online/indicator/indicator_type_ma.h"
namespace indi = mdtx::online::indicator;

using cma = unary1<indi::cma>;
using sma = unary1<indi::sma>;
using tma = unary1<indi::tma>;
using wma = unary1<indi::wma>;
using hma = unary1<indi::hma>;
using ema = unary1<indi::ema>;
using dema = unary1<indi::dema>;
using tema = unary1<indi::tema>;
using t3ma = unary1<indi::t3ma>;
using ewma = unary1<indi::ewma>;
using zlema = unary1<indi::zlema>;
using wilders = unary1<indi::wilders>;

using vwma = binary1<indi::vwma>;
using evwma = binary1<indi::evwma>;

using vidya = unary1<indi::vidya>;
using kama = unary1<indi::kama>;
using mae = unary1<indi::mae>;

void bind_indi_ma(py::module &m)
{
    auto mod = m.def_submodule("ma", "Moving averages");
    {
        auto v = py::class_<cma>(mod, "cma")
                     .def(py::init())
                     .def("run", &cma::run, py::arg("x"), "Run calc")
                     .def("run", &cma::run2, py::arg("x"), "Run batch calc");
        v.doc() = R"mydoc(
                    Cumulative moving average)mydoc";
    }
    {
        auto v = py::class_<sma>(mod, "sma")
                     .def(py::init<int>(), py::arg("period"))
                     .def("run", &sma::run, py::arg("x"), "Run calc")
                     .def("run", &sma::run2, py::arg("x"), "Run batch calc");
        v.doc() = R"mydoc(
                    Simple moving average
                    Args:
                        period (int) : MA period)mydoc";
    }
    {
        auto v = py::class_<tma>(mod, "tma")
                     .def(py::init<int>(), py::arg("period"))
                     .def("run", &tma::run, py::arg("x"), "Run calc")
                     .def("run", &tma::run2, py::arg("x"), "Run batch calc");
        v.doc() = R"mydoc(
                    Triangular moving average
                    Args:
                        period (int) : MA period)mydoc";
    }
    {
        auto v = py::class_<wma>(mod, "wma")
                     .def(py::init<int>(), py::arg("period"))
                     .def("run", &wma::run, py::arg("x"), "Run calc")
                     .def("run", &wma::run2, py::arg("x"), "Run batch calc");
        v.doc() = R"mydoc(
                    Weighted (linear) moving average
                    Args:
                        period (int) : MA period)mydoc";
    }
    {
        auto v = py::class_<hma>(mod, "hma")
                     .def(py::init<int>(), py::arg("period"))
                     .def("run", &hma::run, py::arg("x"), "Run calc")
                     .def("run", &hma::run2, py::arg("x"), "Run batch calc");
        v.doc() = R"mydoc(
                    Hull (triple linear) moving average
                    Args:
                        period (int) : MA period)mydoc";
    }
    {
        auto v = py::class_<ema>(mod, "ema")
                     .def(py::init<int>(), py::arg("period"))
                     .def("run", &ema::run, py::arg("x"), "Run calc")
                     .def("run", &ema::run2, py::arg("x"), "Run batch calc");
        v.doc() = R"mydoc(
                    Exponential moving average
                    Args:
                        period (int) : MA period)mydoc";
    }
    {
        auto v = py::class_<dema>(mod, "dema")
                     .def(py::init<int>(), py::arg("period"))
                     .def("run", &dema::run, py::arg("x"), "Run calc")
                     .def("run", &dema::run2, py::arg("x"), "Run batch calc");
        v.doc() = R"mydoc(
                    Double exponential moving average
                    Args:
                        period (int) : MA period)mydoc";
    }
    {
        auto v = py::class_<tema>(mod, "tema")
                     .def(py::init<int>(), py::arg("period"))
                     .def("run", &tema::run, py::arg("x"), "Run calc")
                     .def("run", &tema::run2, py::arg("x"), "Run batch calc");
        v.doc() = R"mydoc(
                    Triple exponential moving average
                    Args:
                        period (int) : MA period)mydoc";
    }
    {
        auto v = py::class_<t3ma>(mod, "t3ma")
                     .def(py::init<int>(), py::arg("period"))
                     .def("run", &t3ma::run, py::arg("x"), "Run calc")
                     .def("run", &t3ma::run2, py::arg("x"), "Run batch calc");
        v.doc() = R"mydoc(
                    T3 moving average
                    Args:
                        period (int) : MA period)mydoc";
    }
    {
        auto v = py::class_<ewma>(mod, "ewma")
                     .def(py::init<int>(), py::arg("period"))
                     .def("run", &ewma::run, py::arg("x"), "Run calc")
                     .def("run", &ewma::run2, py::arg("x"), "Run batch calc");
        v.doc() = R"mydoc(
                    Exponential windowed moving average
                    Args:
                        period (int) : MA period)mydoc";
    }
    {
        auto v = py::class_<zlema>(mod, "zlema")
                     .def(py::init<int>(), py::arg("period"))
                     .def("run", &zlema::run, py::arg("x"), "Run calc")
                     .def("run", &zlema::run2, py::arg("x"), "Run batch calc");
        v.doc() = R"mydoc(
                    Zero-lag exponential moving average
                    Args:
                        period (int) : MA period)mydoc";
    }
    {
        auto v = py::class_<wilders>(mod, "wilders")
                     .def(py::init<int>(), py::arg("period"))
                     .def("run", &wilders::run, py::arg("x"), "Run calc")
                     .def("run", &wilders::run2, py::arg("x"), "Run batch calc");
        v.doc() = R"mydoc(
                    Wilder's moving average
                    Args:
                        period (int) : MA period)mydoc";
    }

    {
        auto v = py::class_<vwma>(mod, "vwma")
                     .def(py::init<int>(), py::arg("period"))
                     .def("run", &vwma::run, py::arg("x"), py::arg("w"), "Run calc")
                     .def("run", &vwma::run2, py::arg("x"), py::arg("w"), "Run batch calc");
        v.doc() = R"mydoc(
                    Volume weighted moving average
                    Args:
                        period (int) : MA period)mydoc";
    }
    {
        auto v = py::class_<evwma>(mod, "evwma")
                     .def(py::init<int>(), py::arg("period"))
                     .def("run", &evwma::run, py::arg("x"), py::arg("w"), "Run calc")
                     .def("run", &evwma::run2, py::arg("x"), py::arg("w"), "Run batch calc");
        v.doc() = R"mydoc(
                    Elastic volume weighted moving average
                    Args:
                        period (int) : MA period)mydoc";
    }

    {
        auto v = py::class_<vidya>(mod, "vidya")
                     .def(py::init<int, int>(), py::arg("fast_period"), py::arg("slow_period"))
                     .def("run", &vidya::run, py::arg("x"), "Run calc")
                     .def("run", &vidya::run2, py::arg("x"), "Run batch calc");
        v.doc() = R"mydoc(
                    Variable index dynamic moving average
                    Args:
                        fast_period (int) : fast MA period,
                        slow_period (int) : slow MA period)mydoc";
    }
    {
        auto v = py::class_<kama>(mod, "kama")
                     .def(py::init<int>(), py::arg("period"))
                     .def("run", &kama::run, py::arg("x"), "Run calc")
                     .def("run", &kama::run2, py::arg("x"), "Run batch calc");
        v.doc() = R"mydoc(
                    Kaufman adaptive moving average
                    Args:
                        period (int) : MA period)mydoc";
    }
    {
        auto v = py::class_<mae>(mod, "mae")
                     .def(py::init<int>(), py::arg("period"))
                     .def("run", &mae::run, py::arg("x"), "Run calc")
                     .def("run", &mae::run2, py::arg("x"), "Run batch calc");
        v.doc() = R"mydoc(
                    Mean average error over moving window
                    Args:
                        period (int) : MA period)mydoc";
    }
}
